package com.chenchao.thread;

/**
 * @encoding : UTF-8
 * @Time : 2020/11/18 11:10
 * @Author : Chen Chao
 * @File : javaSE.com.chenchao.javathread.Test18.java
 * @Software : IntelliJ IDEA
 * @since : 1.8
 * 管程法
 */
public class Test18 {
    public static void main(String[] args) {
        Container container = new Container();
        Thread thread1 = new Thread(new Producer(container));
        Thread thread2 = new Thread(new Consumer(container));
        thread2.start();
        thread1.start();
    }
}

/**
 * 缓冲区
 */
class Container {
    private int count = -1;
    //容器计数器，-1表示没鸡了
    private Chicken[] chickens = new Chicken[1];

    /**
     * 拿出鸡
     */
    public synchronized Chicken pop() {
        if (count == -1) {
            System.out.println("没鸡了，吃土");
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if (count < chickens.length) {
            this.notify();
        }
        Chicken chicken=chickens[count--];
        System.out.println("第"+chicken.id+"只鸡已卖出");
        return chicken;

    }

    /**
     * 放入鸡
     */
    public synchronized void push(Chicken chicken) {
        if (count == chickens.length - 1) {
            System.out.println("鸡满了，快吃！");
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("生产了第" + chicken.id + "只鸡");
        chickens[++count] = chicken;
        this.notify();
        //notify一定要放在wait的后面
        //如果生产者和消费者都不wait()的情况下，
        //notify()不会对以后的wait()生效,就会造成死等
        //notify()也要放到生产鸡后面，不然如果只有一个箱子就会炸

    }
}

/**
 * 生产者
 */
class Producer implements Runnable {
    private Container container;

    public Producer(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        /**
         * 今天生产1000只鸡
         */
        for (int i = 1; i < 1001; i++) {
            container.push(new Chicken(i));
        }
    }
}

/**
 * 消费者
 */
class Consumer implements Runnable {
    private Container container;

    public Consumer(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            Chicken pop = container.pop();
        }
    }
}

/**
 * 产品
 */
class Chicken {
    int id;

    public Chicken(int id) {
        this.id = id;
    }
}